home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 2000 edwards@bitchx.dimension6.com
- This is free software distributed under the terms of the
- GNU Public License. See the file COPYING for details.
-
- Modified by drscholl@users.sourceforge.net 2/29/2000.
-
- $Id: timer.c,v 1.9 2001/02/13 08:41:15 drscholl Exp $ */
-
- #include <time.h>
- #include <stdlib.h>
- #include "opennap.h"
- #include "debug.h"
-
- typedef struct _timerstruct
- {
- struct _timerstruct *next;
- timer_cb_t func;
- void *arg;
- time_t next_time;
- time_t interval;
- int events;
- unsigned int refnum;
- }
- TIMER;
-
- static TIMER *Pending_Timers = NULL;
- static unsigned int TimerRef = 0;
-
- static void
- schedule_timer (TIMER * ntimer)
- {
- TIMER **slot;
-
- if (!ntimer->events)
- return;
-
- /* we've created it, now put it in order */
- for (slot = &Pending_Timers; *slot; slot = &(*slot)->next)
- {
- if (ntimer->next_time < (*slot)->next_time)
- break;
- }
- ntimer->next = *slot;
- *slot = ntimer;
- }
-
- /* returns the refnum */
- int
- add_timer (int interval, int events, timer_cb_t func, void *arg)
- {
- TIMER *new;
-
- if (!events)
- return -1;
- new = CALLOC (1, sizeof (TIMER));
- if (!new)
- {
- OUTOFMEMORY ("add_timer");
- return -1;
- }
- new->next_time = global.current_time + interval;
- new->interval = interval;
- new->func = func;
- new->arg = arg;
- new->events = events;
- new->refnum = TimerRef++;
- schedule_timer (new);
-
- return new->refnum;
- }
-
- void
- exec_timers (time_t now)
- {
- TIMER *current;
-
- while (Pending_Timers && Pending_Timers->next_time <= now)
- {
- current = Pending_Timers;
- Pending_Timers = current->next;
- (*current->func) (current->arg);
- switch (current->events)
- {
- case 0:
- FREE (current);
- break;
- default:
- current->events--;
- case -1:
- /* reschedule */
- current->next_time = global.current_time + current->interval;
- schedule_timer (current);
- break;
- }
- }
- }
-
- /* returns the time offset at which the next pending event is scheduled */
- time_t next_timer (void)
- {
- if (Pending_Timers)
- {
- if (Pending_Timers->next_time < global.current_time)
- return 0; /* now! */
- return (Pending_Timers->next_time - global.current_time);
- }
- return -1;
- }
-
- void
- free_timers (void)
- {
- TIMER *ptr;
-
- while (Pending_Timers)
- {
- ptr = Pending_Timers;
- Pending_Timers = Pending_Timers->next;
- FREE (ptr);
- }
- }
-
- /* change the interval at which a timer occurs. note that this does not
- * reschedule a currently pending event, and only affect subsequent calls
- */
- void
- timer_set_interval (unsigned int refnum, int interval)
- {
- TIMER *t = Pending_Timers;
-
- for (; t; t = t->next)
- if (t->refnum == refnum)
- {
- t->interval = interval;
- break;
- }
- }
-